// DlgNetTools.cpp : implementation file
//

#include "stdafx.h"
#include "NetTools.h"
#include "DlgNetTools.h"


// CDlgNetTools dialog

IMPLEMENT_DYNAMIC(CDlgNetTools, CDialog)

CDlgNetTools::CDlgNetTools(CWnd* pParent /*=NULL*/)
	: CDialog(CDlgNetTools::IDD, pParent)
{
}

CDlgNetTools::~CDlgNetTools()
{
}

void CDlgNetTools::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_EDIT_HOSTNAME, m_oHostName);
	DDX_Control(pDX, IDC_LIST_RESULTS, m_oListResults);
}


BEGIN_MESSAGE_MAP(CDlgNetTools, CDialog)
	ON_BN_CLICKED(IDC_BUTTON_PING, &CDlgNetTools::OnBnClickedButtonPing)
	ON_BN_CLICKED(IDC_BUTTON_TRACEROUTE, &CDlgNetTools::OnBnClickedButtonTraceroute)
END_MESSAGE_MAP()

BOOL CDlgNetTools::OnInitDialog() 
{
	CDialog::OnInitDialog();

	m_oListResults.InsertColumn(0, _T("I.P. Address"), LVCFMT_LEFT, 150);
	m_oListResults.InsertColumn(1, _T("RTT"), LVCFMT_LEFT, 50);
	
	return TRUE;
}

// CDlgNetTools message handlers

void CDlgNetTools::OnBnClickedButtonPing()
{
	CWaitCursor cur;

	m_oListResults.DeleteAllItems();

	CString sAddress;
	m_oHostName.GetWindowText(sAddress);

	char szHost[256];
	ustrncpy(szHost, sAddress, 256);

	DWORD dwAddress = inet_addr(szHost);
	if(INADDR_NONE == dwAddress)
	{
		hostent* host = gethostbyname(szHost);
		if(host)
		{
			memcpy(&dwAddress, host->h_addr, host->h_length);
		}
		else
		{
			AfxMessageBox(_T("Failed to resolve hostname"));
			return;
		}
	}

	HANDLE hICmp = IcmpCreateFile();
	for(int i = 0; i < 5; i++)
	{
		CIcmpReply* pReply = new CIcmpReply;
		pReply->m_dwAddress = dwAddress;

		DWORD dw = IcmpSendEcho(hICmp, dwAddress, 0,0, NULL, pReply, sizeof(icmp_echo_reply),500);
		if(0 == dw)
		{
			dw = GetLastError();
			if (dw != 11010)
			{
				CString sError;
				sError.Format(_T("Failed to ping. Error code: %s"), GetWin32ErrorString(dw));
				AfxMessageBox(sError);
				break;
			}
		}
		if(ERROR_SUCCESS != pReply->m_dwError)
		{
			CString sError = GetWin32ErrorString(pReply->m_dwError);
			m_oListResults.InsertItem(m_oListResults.GetItemCount(), sError, 0);
		}
		else
		{
			in_addr Address;
			Address.S_un.S_addr = pReply->Address;

			CString sRetAddress;
			sRetAddress.Format(_T("%d.%d.%d.%d"), 
								Address.S_un.S_un_b.s_b1,
								Address.S_un.S_un_b.s_b2,
								Address.S_un.S_un_b.s_b3,
								Address.S_un.S_un_b.s_b4);

			CString sRTT;
			sRTT.Format(_T("%ld"), pReply->RoundTripTime);

			int nItem = m_oListResults.InsertItem(m_oListResults.GetItemCount(), sRetAddress, 0);
			m_oListResults.SetItem(nItem, 1, LVIF_TEXT, sRTT, 0, 0, 0, 0);
		}
		delete pReply;
	}
	IcmpCloseHandle(hICmp);
}

void CDlgNetTools::OnBnClickedButtonTraceroute()
{
	CWaitCursor cur;

	m_oListResults.DeleteAllItems();

	CString sAddress;
	m_oHostName.GetWindowText(sAddress);

	char szHost[256];
	ustrncpy(szHost, sAddress, 256);

	DWORD dwAddress = inet_addr(szHost);
	if(INADDR_NONE == dwAddress)
	{
		hostent* host = gethostbyname(szHost);
		if(host)
		{
			memcpy(&dwAddress, host->h_addr, host->h_length);
		}
		else
		{
			AfxMessageBox(_T("Failed to resolve hostname"));
			return;
		}
	}

	HANDLE hICmp = IcmpCreateFile();
	for(int nIdx = 1; nIdx < 254; nIdx++)
	{
		CIcmpReply* pReply = new CIcmpReply;
		pReply->m_dwAddress = dwAddress;

		ip_option_information ioi;
		memset(&ioi, 0, sizeof(ip_option_information));
		ioi.Ttl = nIdx;

		DWORD dw = IcmpSendEcho(hICmp, dwAddress, 0,0, &ioi, pReply, sizeof(icmp_echo_reply),500);
		if(0 == dw)
		{
			dw = GetLastError();
			if (dw != 11010) // If error is other than timeout - display a message
			{
				CString sError;
				sError.Format(_T("Failed to trace route. Error code: %s"), GetWin32ErrorString(dw));
				AfxMessageBox(sError);
				break;
			}
		}
		if(ERROR_SUCCESS != pReply->m_dwError)
		{
			CString sError = GetWin32ErrorString(pReply->m_dwError);
			m_oListResults.InsertItem(m_oListResults.GetItemCount(), sError, 0);
			break;
		}
		else
		{
			in_addr Address;
			Address.S_un.S_addr = pReply->Address;

			CString sRetAddress;
			sRetAddress.Format(_T("%d.%d.%d.%d"), 
								Address.S_un.S_un_b.s_b1,
								Address.S_un.S_un_b.s_b2,
								Address.S_un.S_un_b.s_b3,
								Address.S_un.S_un_b.s_b4);

			CString sRTT;
			sRTT.Format(_T("%ld"), pReply->RoundTripTime);

			int nItem = m_oListResults.InsertItem(m_oListResults.GetItemCount(), sRetAddress, 0);
			m_oListResults.SetItem(nItem, 1, LVIF_TEXT, sRTT, 0, 0, 0, 0);
		}
		if(pReply->Address == dwAddress)
		{
			delete pReply;
			break;
		}
		delete pReply;
	}
	IcmpCloseHandle(hICmp);
}
